# -*- coding: utf-8 -*-
#!/usr/bin/python2.7

from ldap3 import Server, Connection, ALL, NTLM, MODIFY_REPLACE
import base64
import hashlib
import binascii
import ldap3
import re
import datetime

LDAP_HOST = "10.0.1.2:389"
LDAP_ADMIN = "cn=admin,dc=floa,dc=vip"
LDAP_ADMIN_PASSWORD = "admin"
LDAP_BASE_DN = "dc=floa,dc=vip"

class LdapAuthAPI(object):
    def __init__(self, LDAP_HOST, LDAP_ADMIN, LDAP_ADMIN_PASSWORD, LDAP_BASE_DN):
        self.LDAP_HOST = LDAP_HOST
        self.LDAP_ADMIN = LDAP_ADMIN
        self.LDAP_ADMIN_PASSWORD = LDAP_ADMIN_PASSWORD
        self.LDAP_BASE_DN = LDAP_BASE_DN
    
    def connect(self):
        '''
        连接ldap
        '''
        server = Server(LDAP_HOST, get_info=ALL)
        conn = Connection(server, LDAP_ADMIN, LDAP_ADMIN_PASSWORD, auto_bind=True)
        return conn
 
    def get_users(self): 
        '''
        获取用户列表
        ''' 
        conn = self.connect()
        conn.search(self.LDAP_BASE_DN, "(objectclass=person)", attributes=["givenName", "sn", "cn", "uid", "mail", "displayName", "objectClass", "homeDirectory", "loginShell", "gidNumber", "uidNumber", "userPassword"])
        ldap_users = conn.entries
        return ldap_users

    def auth(self, username, password):
        '''
        用户验证
        '''
        ou = self.get_user_ou(username)
        user = "cn=%s,%s,%s" % (username, ou, self.LDAP_BASE_DN)
        server = Server(LDAP_HOST, get_info=ALL)
        c = Connection(
            server, 
            user=user,
            password=password)
        ret = c.bind()
        if ret:
            c.unbind()
            return True
        else:
            return False

    def add_ou(self, ou, oid):
        ''' 
        添加部门
        '''
        try:
            conn = self.connect()
            conn.add(ou, 'organizationalUnit', {"st": oid})
        except Exception as e:
            result = e
            code = "500"
        else:
            result = conn.result
        return result

    def get_ou(self):
        '''
        获取所有部门
        '''
        try:
            conn = self.connect()
            conn.search(self.LDAP_BASE_DN, '(ou=*)')
        except Exception as e:
            result = e
            code = "500"
        else:
            result = conn.entries
        return result

    def get_user_ou(self, username):
        '''
        获取用户部门
        '''
        ldaps_users = self.get_users() 
        ou = str([item for item in ldaps_users if re.search(username, str(item))][0]).split(',')[1]
        return ou 

    def delete_user(self, ou, username):
        '''
        删除用户
        '''
        try:
            conn = self.connect()
            #print("cn="+ username +",o="+ ou +","+ self.LDAP_BASE_DN)
            conn.delete(dn="cn="+ username +",o="+ ou +","+ self.LDAP_BASE_DN)
        except Exception as e:
            result = e
            code = "500"
        else:
            result = conn.result
            errmsg = "200"

        return result

    def add_user(self, ou, username, password, mail, givenname, sn):
        '''
        添加用户
        '''
        uidnumber = str(datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
        objectclass = ["top", "inetOrgPerson", "posixAccount"]
        password = self.base64passwd(password)

        try:
            conn = self.connect()
            conn.add(
                "cn="+ username +",o="+ ou +","+ self.LDAP_BASE_DN, 
                objectclass, 
                {"loginShell": "/bin/bash", 
                 "cn": username, 
                 "userPassword": password.encode(), 
                 "mail": mail, 
                 "displayName": givenname + sn, 
                 "givenName": givenname, 
                 "sn": sn, 
                 "homeDirectory": "/home/users/"+ username, 
                 "uid": username, 
                 "uidNumber": uidnumber, 
                 "gidNumber": "0"}
            )
        except Exception as e:
            result = e
        else:
            result = conn.result
     
        return result

    def base64passwd(self, password):
        '''
        密码格式化
        '''
        md5String=hashlib.md5(password.encode('utf-8')).hexdigest()
        # ascii码加密串
        binasciiString = binascii.a2b_hex(md5String)
        # base64加密串
        base64String = base64.b64encode(binasciiString).decode('utf=8')
        password = "{MD5}" + base64String
        return password

obj = LdapAuthAPI(LDAP_HOST, LDAP_ADMIN, LDAP_ADMIN_PASSWORD, LDAP_BASE_DN)
#添加用户
#print(obj.add_user("dev", "maokailu", "Fuliao10086", "maokailu@ichamet.com", "毛", "凯璐"))
#添加部门
#print(obj.add_ou("ou=backend,ou=fuliao,dc=ipaychat,dc=net", 3))
print(obj.get_users())
#print(obj.get_ou())
#print(obj.auth("wusheng", "123456"))
#print(obj.delete_user("dev", "maokailu"))
